﻿using System;
using EPiServer.Core;
using TemplateFoundation.Core;
using TemplateFoundation.PageTypes;

namespace TemplateFoundation.Feeds
{
    /// <summary>
    /// Represents a single RSS item
    /// </summary>
    /// <seealso cref="RssItemCollection"/>
    /// <seealso cref="RssChannel"/>
    public class RssItem
    {
        /// <summary>
        /// Gets or sets the title
        /// </summary>
        public string Title { get; set; }

        /// <summary>
        /// Gets or sets the link URL
        /// </summary>
        public string Link { get; set; }

        /// <summary>
        /// Gets or sets the description
        /// </summary>
        public string Description { get; set; }

        /// <summary>
        /// Gets or sets the author
        /// </summary>
        public string Author { get; set; }

        /// <summary>
        /// Gets or sets comments
        /// </summary>
        public string Comments { get; set; }

        /// <summary>
        /// Gets or sets the GUID
        /// </summary>
        public string Guid { get; set; }

        /// <summary>
        /// Gets or sets the publishing date
        /// </summary>
        public DateTime Date { get; set; }

        /// <summary>
        /// Gets or sets categories
        /// </summary>
        public string[] Categories { get; set; }

        /// <summary>
        /// Gets or sets the language
        /// </summary>
        /// <remarks>This is not included in the feed, but used for validation when adding items to a channel</remarks>
        public string Language { get; set; }

        /// <summary>
        /// Initializes an empty RSS item
        /// </summary>
        public RssItem()
        {
            Author = string.Empty;
            Description = string.Empty;
            Guid = System.Guid.NewGuid().ToString();
            Link = string.Empty;
            Title = string.Empty;
            Categories = new string[0];
            Language = string.Empty;
            Comments = string.Empty;
        }

        /// <summary>
        /// Initializes a new RSS item based on a page
        /// </summary>
        /// <param name="page">The page used to populate the RSS item</param>
        /// <param name="includeFullContent">Whether or not to include full content or just the description</param>
        /// <remarks>Full content is only supported for pages implementing the IStandardPage interface</remarks>
        public RssItem(PageTypeBase page, bool includeFullContent) : this(page,includeFullContent,null)
        {
                        
        }

        /// <summary>
        /// Initializes a new RSS item based on a page
        /// </summary>
        /// <param name="page">The page used to populate the RSS item</param>
        /// <param name="includeFullContent">Whether or not to include full content or just the description</param>
        /// <param name="datePropertyName">Used to specify the name of the page type property to use for the item's date property, if other than PageStartPublish</param>
        /// <remarks>Full content is only supported for pages implementing the IStandardPage interface</remarks>
        public RssItem(PageTypeBase page, bool includeFullContent, string datePropertyName)
        {
            // Use Author string property if set, otherwise fallback to the ContactPerson property
            Author = !string.IsNullOrEmpty(page.Author)
                         ? page.Author
                         : (!PageReference.IsNullOrEmpty(page.PageContact)
                                ? page.PageContact.GetPage<ContactPageBase>().Name
                                : string.Empty);

            if (includeFullContent && page is IStandardPage && !string.IsNullOrEmpty(((IStandardPage)page).MainBody))
            {
                var content = ((IStandardPage) page).MainBody;

                var siteUrl = EPiServer.Configuration.Settings.Instance.SiteUrl.ToString();

                if(siteUrl.EndsWith("/"))
                {
                    siteUrl = siteUrl.Substring(0, siteUrl.Length - 1);
                }

                // Ensure absolute paths when relative URLs are included using quotes...
                content = content.Replace("src=\"/", string.Format("src=\"{0}/", siteUrl));
                content = content.Replace("href=\"/", string.Format("href=\"{0}/", siteUrl));

                // ...and with single quotes
                content = content.Replace("src='/", string.Format("src='{0}/", siteUrl));
                content = content.Replace("href='/", string.Format("href='{0}/", siteUrl));

                // ...and with NO quotes
                content = content.Replace("src=/", string.Format("src={0}/", siteUrl));
                content = content.Replace("href=/", string.Format("href={0}/", siteUrl));

                Description = string.Format("<![CDATA[ {0} ]]>", content);
            }
            else
            {
                Description = page.Description;
            }

            // Set item date
            if (string.IsNullOrEmpty(datePropertyName))
            {
                Date = page.StartPublish;
            }
            else
            {
                var dateProperty = page[datePropertyName];

                DateTime date;

                if (dateProperty == null || !(dateProperty is DateTime)) // Specified property doesn't exist or is of incorrect type, fall back to StartPublish
                {
                    date = page.StartPublish;
                }
                else
                {
                    date = (DateTime) dateProperty;
                }

                Date = date;
            }

            Guid = page.PageGuid.ToString();
            Link = page.GetFriendlyUrl(true);
            Title = page.Title ?? page.PageName;
            Categories = page.Tags.ToStringArray();
            Language = page.LanguageBranch;
            Comments = string.Empty; // Not currently supported
        }

        /// <summary>
        /// Initializes a new RSS item based on a page
        /// </summary>
        /// <param name="page">The page used to populate the RSS item</param>
        public RssItem(PageTypeBase page) : this(page, false)
        {
        }
    }
}
